﻿using System;
using System.Collections.Generic;
using System.Linq;
using Xoohoo.Extensions;
using Xoohoo.Infrastructure;
using Xoohoo.Models;
using Xoohoo.Models.InputModels;
using Xoohoo.Repositories;

namespace Xoohoo.Services
{
    public class UserGroupService : IUserGroupService
    {
        private readonly IUserGroupRepository _repository;
        private readonly ICacheModule _cache;
        private readonly string _userGroupyListCacheKey = "UserGroupList";

        #region IUserGroupService Members

        public UserGroupService(IUserGroupRepository repository, IModuleRegistry modulesLoaded)
        {
            this._repository = repository;
            this._cache = modulesLoaded.GetModules<ICacheModule>().Last();
        }

        public UserGroup GetItem(Guid userGroupID)
        {
            return _repository.GetItem(userGroupID);
        }

        public UserGroup GetItem(string userGroupName)
        {
            return _repository.GetItem(userGroupName);
        }

        public List<UserGroup> GetList(Guid? parentID = null)
        {
            List<UserGroup> userGroups = GetListFromCache();
            if (!userGroups.IsNullOrEmpty())
                return CloneUserGroups(userGroups);
            else
                return _repository.GetList(parentID);
        }

        public ModelResult Save(UserGroupInput userGroupInput)
        {
            ModelResult modelResult = ValidateUserGroup(userGroupInput);
            if (!modelResult.IsValid) return modelResult;

            _repository.Save(userGroupInput);
            _cache.Invalidate(_userGroupyListCacheKey);

            return modelResult;
        }

        public bool Remove(Guid userGroupID)
        {
            bool result = _repository.Remove(userGroupID);
            if (result)
                _cache.Invalidate(_userGroupyListCacheKey);
            return result;
        }

        public bool Move(Guid userGroupID, MovingTarget target)
        {
            bool result = _repository.Move(userGroupID, target);
            if (result)
                _cache.Invalidate(_userGroupyListCacheKey);
            return result;
        }

        #endregion

        #region Private Methods

        /// <summary>
        /// 验证用户组名称是否已经被使用
        /// </summary>
        /// <param name="userGroupInput"></param>
        /// <param name="validationState"></param>
        private ModelResult ValidateUserGroup(UserGroupInput userGroupInput)
        {
            ModelResult modelResult = new ModelResult();
            UserGroup foundUserGroup = _repository.GetItem(userGroupInput.UserGroupName);

            if (foundUserGroup != null && userGroupInput.UserGroupID != foundUserGroup.UserGroupID)
            {
                modelResult.Errors.Add("用户组名称【" + userGroupInput.UserGroupName + "】已经被使用");
            }
            return modelResult;
        }

        /// <summary>
        /// 克隆列表
        /// </summary>
        /// <param name="source"></param>
        /// <returns></returns>
        private List<UserGroup> CloneUserGroups(IEnumerable<UserGroup> source)
        {
            if (source.IsNullOrEmpty())
                return new List<UserGroup>();

            //深度克隆
            return (source.DeepClone() as IEnumerable<UserGroup>).ToList();

            /*
            List<UserGroup> userGroups = new List<UserGroup>();
            foreach (var item in source)
            {
                userGroups.Add(new UserGroup
                {
                    ParentID = item.ParentID,
                    UserGroupID = item.UserGroupID,
                    UserGroupName = item.UserGroupName,
                    UserGroupLevel = item.UserGroupLevel,
                    DisplayOrder = item.DisplayOrder,
                    IsSystem = item.IsSystem,
                    Roles = item.Roles == null ? Enumerable.Empty<RoleBasic>() :
                        item.Roles.Select(p=>new RoleBasic{
                             RoleID = p.RoleID,
                             RoleName = p.RoleName,
                             IsSystem = p.IsSystem
                        })
                });
            }
            return userGroups;
            */
        }

        /// <summary>
        /// 创建父节点路径
        /// </summary>
        /// <param name="source"></param>
        /// <param name="target"></param>
        /// <param name="parentID"></param>
        private void CreateParentPath(IEnumerable<UserGroup> source,IList<UserGroup> target, Guid? parentID)
        {
            if (parentID.IsNullOrEmpty() || source == null || target == null) return;

            UserGroup parent = source.FirstOrDefault(m => m.UserGroupID == parentID);
            if (parent != null && target.All(m => m.UserGroupID != parent.UserGroupID)/*避免死循环*/)
            {
                target.Insert(0, parent);
                CreateParentPath(source, target, parent.ParentID);
            }
        }

        private List<UserGroup> GetListFromCache(Guid? parentID = null)
        {
            if (_cache != null)
                return _cache.GetItem<List<UserGroup>>(
                    _userGroupyListCacheKey, () => _repository.GetList(),
                    null
                    );
            else
                return null;
        }

        #endregion

    }
}
